/*
 * AsynSocket.h
 *
 *  Created on: 2012-12-14
 *      Author: yangentao@gmail.com
 */

#pragma once;
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include "NetUtil.h"
#include "BaseSocket.h"
#include "../Thread.h"
#include "../Handler.h"
#include "../String.h"

#define READ_BUF_SIZE	256

namespace yet {

class AsynSocket{
	enum Status{
		statusInit,
		statusConnecting,
		statusConnected,
		statusClosing,
		statusClosed,
		statusWaitWrite,
	};
	class StatusSocket{
	public:
		StatusSocket(AsynSocket* asynSocket);
	public:
		void bind();
		void connect();//OnConnect
		void listen();
		void accept();//OnAccept
		void send();//OnSendContinue;
		void recv();//OnReceived
		void close();


	public:
		AsynSocket* asynSocket;
	};
public:
	AsynSocket();
	AsynSocket(SOCKET s);
	virtual ~AsynSocket();
public:
	//FD_READ| FD_WRITE| FD_OOB| FD_ACCEPT| FD_CONNECT| FD_CLOSE
	bool select();
	//netEvents: FD_XXX
	bool select(long netEvents);
	void close();
	//return
	//true, ok
	//false, failed, wait and try again later, you need check status if failed
	//please check status before send
	int send(String buf);
public:
	void setHandler(boost::shared_ptr<Handler> handler);

	DWORD threadTask(void* argp);
	void messageHandler(Message& msg);
private:
	//return, false: quit loop;  true: continue
	bool processEvents();
	void init(SOCKET s);
	void post(Message msg);
public:
	boost::function<void (AsynSocket* es, String buf)> OnReceived;
	boost::function<void (AsynSocket* es)> OnWritable;
	boost::function<void (AsynSocket* es)> OnConnected;
	boost::function<void (AsynSocket* es, String buf)> OnOOBReceived;
	boost::function<void (AsynSocket* es)> OnAccept;
	boost::function<void (AsynSocket* es)> OnClosed;
public:
	BaseSocket baseSock;
	HANDLE selectEvent;
	Thread recvThread;
	boost::shared_ptr<Handler> msgHandler;
	bool volatile connected;

public:
};

} /* namespace yet */
